import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;

public class WorldViewer {

	public static Snapshot current;
	private final JFrame frame;
	//closest to star (lightest)
	private final Color GRAY1 = new Color(232, 232, 232);
	//next step away (medium)
	private final Color GRAY2 = new Color(179, 179, 179);
	//one more step away (medium-dark)
	private final Color GRAY3 = new Color(126, 126, 126);
	//furthest step away (darkest)
	private final Color GRAY4 = new Color(73, 73, 73);

	public WorldViewer() {
		this(true);
	}

	public WorldViewer(boolean enable) {
		frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setTitle("Constellations");
		frame.setSize(800, 600);
		frame.setLocation(100, 100);
		frame.add(new WorldPane());
	}

	public void showWorld(int[][] world) {
		showWorld(new Snapshot(world));
	}

	private void showWorld(Snapshot newSnapshot) {
		current = newSnapshot;
		update();
	}

	/** Updates the painted display based on the current Snapshot. */
	private void update() {
		frame.setVisible(true); // Make sure the window is shown.
		frame.repaint();
	}

	/** JPanel for painting a World on the screen. */
	private class WorldPane extends JPanel {

		private static final long serialVersionUID = 1L;

		public WorldPane() {
			setBorder(BorderFactory.createEmptyBorder());
		}

		@Override
		public void paint(Graphics graphics) {
			int[][] sky = current.sky;
			Graphics2D g = (Graphics2D) graphics;
			final Insets insets = getInsets();
			final int width = getWidth();
			final int height = getHeight();

			g.setColor(Color.BLACK);
			g.fillRect(0, 0, width, height);
			
			if (sky == null) {
				// Leave a blank screen.
			} else {
				// Paint each tile in the proper location.
				int size = sky.length;
				double tileWidth = Math.min(
						width - insets.left - insets.right,
						height - insets.top - insets.bottom) / (double) size;
				final int TOTAL = Config.starComponents.size();
				int counter = Config.starComponents.size();
				for (int row = 0; row < size; row++) {
					for (int col = 0; col < size; col++) {
						int tile = sky[row][col];
						// Choose a color based on the bitmap status.
						if (tile == Config.SKY) {
							g.setColor(Color.BLACK);
						} else if (tile == Config.STAR) {
							g.setColor(Color.WHITE);
						} else if (tile == Config.GRAY1) {
							g.setColor(GRAY1);
						} else if (tile == Config.GRAY2) {
							g.setColor(GRAY2);
						} else if (tile == Config.GRAY3) {
							g.setColor(GRAY3);
						} else if (tile == Config.GRAY4) {
							g.setColor(GRAY4);
						} else {
							continue;
						}

						Config.starComponents.get(TOTAL-counter).setGraphXCoord((int)((col + 0.1) * tileWidth + insets.left));
						Config.starComponents.get(TOTAL-counter).setGraphYCoord((int)((row + 0.1) * tileWidth + insets.left));
						// Paint a circle to represent the star fragment.
						g.fill(new Ellipse2D.Double(
								(col) * tileWidth + insets.left,
								(row) * tileWidth + insets.top,
								tileWidth * 0.9, tileWidth * 0.9));
						counter--;
					}
				}
				
				//change maxSpanTreeEdgeList below to edgeList to make complete graph
				g.setColor(Color.YELLOW);
				for (int i = 0; i < Config.maxSpanTreeEdgeList.size(); i++) {
					g.drawLine(Config.maxSpanTreeEdgeList.get(i).getA().getGraphXCoord(),
							Config.maxSpanTreeEdgeList.get(i).getA().getGraphYCoord(),
							Config.maxSpanTreeEdgeList.get(i).getB().getGraphXCoord(),
							Config.maxSpanTreeEdgeList.get(i).getB().getGraphYCoord());
				}
//				//point 1 to point 2
//				g.drawLine((int)((216 + 0.1) * tileWidth + insets.left),
//						(int)((10 + 0.1) * tileWidth + insets.left),
//						(int)((190 + 0.1) * tileWidth + insets.left),
//						(int)((150 + 0.1) * tileWidth + insets.left));
//				// point 2 to point 4
//				g.drawLine((int)((190 + 0.1) * tileWidth + insets.left),
//						(int)((150 + 0.1) * tileWidth + insets.left),
//						(int)((270 + 0.1) * tileWidth + insets.left),
//						(int)((60 + 0.1) * tileWidth + insets.left));
//				// point 4 to point 5
//				g.drawLine((int)((160 + 0.1) * tileWidth + insets.left),
//						(int)((60 + 0.1) * tileWidth + insets.left),
//						(int)((270 + 0.1) * tileWidth + insets.left),
//						(int)((60 + 0.1) * tileWidth + insets.left));
//				// point 5 point 3
//				g.drawLine((int)((250 + 0.1) * tileWidth + insets.left),
//						(int)((150 + 0.1) * tileWidth + insets.left),
//						(int)((160 + 0.1) * tileWidth + insets.left),
//						(int)((60 + 0.1) * tileWidth + insets.left));
//				g.drawLine((int)((216 + 0.1) * tileWidth + insets.left),
//						(int)((10 + 0.1) * tileWidth + insets.left),
//						(int)((250 + 0.1) * tileWidth + insets.left),
//						(int)((150 + 0.1) * tileWidth + insets.left));
			}
		}
	}

	static class Snapshot {
		public final int[][] sky;
		public Snapshot(int[][] sky) {
			this.sky = sky;
		}
	}

}